﻿using System;

namespace Lesson5_成员属性
{
    #region 一 成员属性的基本概念
    //基本概念：
    // 1.用于保护成员变量
    // 2.为成员变量的获取和赋值添加逻辑处理
    // 3.解决访问修饰符的局限性
    //   访问：可获取 可修改
    //   public——内部外部可访问
    //   private——仅内部可访问
    //   protected——内部和子类可访问
    //   属性可以让成员变量在外部
    //   仅能修改 不能获取，或仅能获取 不能修改
    #endregion

    #region 二 成员属性的基本语法
    //访问修饰符 属性类型 属性名
    //{
    //     get{}
    //     set{} 
    //}
    class Person
    {
        private string name;        //字段（是类、结构体或枚举中声明的变量。字段是类的成员之一，用于存储与类实例相关的数据。与属性不同，字段通常是私有的，并且直接存储数据值，而不是通过访问器进行访问）
        private int age;
        public int money;
        private bool sex;

        //属性的命名一般使用 帕斯卡命名法
        public string Name          //属性
        {
            //get访问器 用于读取属性值
            get
            {
                //可以进行一些逻辑操作
                return name;
            }
            //set访问器 用于设置属性值
            set
            {
                //可以进行一些逻辑操作
                //关键字: value 用于表示外部传入的值
                name = value;
            }
        }

        //成员属性对成员变量的保护体现在哪里
        public int Money
        {
            get
            {
                //进行解密处理
                return money - 5;
            }
            set
            {
                //对成员变量money进行简单的加密处理：成员变量money存储的值并不等于set访问器设置的值
                money = value + 5;
            }
        }

        #region 四 get与set可以用访问修饰符修饰
        // 注意
        // 1.若不加访问修饰符 默认使用属性的访问修饰符
        // 2.访问器前加的访问修饰符 访问权限必须低于属性的访问权限
        // 3.不能让get和set的访问修饰符都低于属性的访问权限（一般不会在两个访问器前都加上访问修饰符 因为这样属性的访问修饰符就没有意义了）
        public int Age
        {
            private get
            {
                return age;
            }
            set
            {
                age = value;
            }
        }
        #endregion

        #region 五 get和set可以只有一个
        //只有一个访问器时 不能加访问修饰符
        //往往我们希望外部只能得到成员变量的值 而不希望其可以被修改 这时就会仅使用一个get访问器
        //这样的只读属性可以通过构造函数进行赋值
        //这样的属性适用于那些类的固定不变的 且需要被读取的属性
        public bool Sex
        {
            get
            {
                return sex;
            }
        }
        #endregion

        #region 六 自动属性
        //自动属性特别使用于不需要在访问器中执行特殊逻辑处理的情况 可以减少代码量
        //编译器会自动为自动属性生成一个匿名的变量
        public int Height
        {
            get;set;
        }
        public int Weight
        {
            get;
        }
        //Height虽然是只读属性 但可以通过构造函数为其赋值
        #endregion
    }
    #endregion


    class Program
    {
        static void Main(string[] args)
        {
            #region 三 成员属性的使用
            Person person = new Person();
            //这里我们使用.来调用成员时 发现并不能直接访问私有的变量
            //这时我们就可以通过调用属性来对成员变量 name 进行读取或设置
            //使用set访问器进行设置
            person.Name = "LiberTy";
            //使用get访问器进行读取
            Console.WriteLine(person.Name);

            person.Money = 5;
            Console.WriteLine(person.Money);
            Console.WriteLine(person.money);
            //可以看出存储进money变量里的值并不是我们为它设置的值 这样就一定程度的实现了对成员变量的保护
            #endregion
        }
    }
}